package com.eduagent.xwqeduagent.api.RealTimeVoiceToTextConversion.service;



import com.eduagent.xwqeduagent.api.RealTimeVoiceToTextConversion.constant.RealTimeASRConstant;
import com.eduagent.xwqeduagent.api.RealTimeVoiceToTextConversion.model.ASRParams;
import com.eduagent.xwqeduagent.api.RealTimeVoiceToTextConversion.model.ASRResult;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import com.eduagent.xwqeduagent.api.RealTimeVoiceToTextConversion.util.AuthUtil;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.stereotype.Service;

/**
 * 实时语音转写服务
 * todo 需要优化
 */
@Service
public class RealTimeASRService {

    /**
     * WebSocket 客户端
     */
    private WebSocketClient client;

    /**
     * 语音转写结果回调接口
     */
    public interface ASRCallback {
        /**
         * 连接建立成功
         * @param sessionId 会话ID
         */
        void onConnected(String sessionId);
        
        /**
         * 接收到转写结果
         * @param result 转写结果
         */
        void onResult(ASRResult result);
        
        /**
         * 发生错误
         * @param errorCode 错误码
         * @param errorMessage 错误信息
         */
        void onError(String errorCode, String errorMessage);
        
        /**
         * 连接关闭
         */
        void onClose();
    }
    
    /**
     * 开始实时语音转写
     *
     * @param params 语音转写参数
     * @param callback 回调接口
     * @throws Exception 连接过程中的异常
     */
    public void startRealTimeASR(ASRParams params, ASRCallback callback) throws Exception {
        // 生成带鉴权参数的URL
        String url = AuthUtil.generateAuthUrl(params == null ? null : params.toQueryString());
        
        // 创建WebSocket客户端
        client = new WebSocketClient(new URI(url)) {
            @Override
            public void onOpen(ServerHandshake handshakedata) {
                // WebSocket连接建立，但需要等待服务端返回started消息才表示握手成功
            }
            
            @Override
            public void onMessage(String message) {
                try {
                    // 解析结果
                    ASRResult result = ASRResult.fromJson(message);
                    
                    // 判断结果类型
                    if ("started".equals(result.getAction())) {
                        // 握手成功
                        callback.onConnected(result.getSid());
                    } else if ("result".equals(result.getAction())) {
                        // 接收到转写结果
                        callback.onResult(result);
                    } else if ("error".equals(result.getAction())) {
                        // 发生错误
                        callback.onError(result.getCode(), result.getDesc());
                    }
                } catch (Exception e) {
                    callback.onError("-1", "解析结果异常: " + e.getMessage());
                }
            }
            
            @Override
            public void onClose(int code, String reason, boolean remote) {
                callback.onClose();
            }
            
            @Override
            public void onError(Exception ex) {
                callback.onError("-1", "WebSocket错误: " + ex.getMessage());
            }
        };
        
        // 设置连接超时
        client.setConnectionLostTimeout(60);
        
        // 连接WebSocket服务器
        client.connect();
    }
    
    /**
     * 发送音频数据
     *
     * @param audioData 音频数据字节数组
     * @throws IOException 发送异常
     */
    public void sendAudioData(byte[] audioData) throws IOException {
        if (client == null || !client.isOpen()) {
            throw new IOException("WebSocket连接未建立或已关闭");
        }
        
        // 发送二进制音频数据
        client.send(audioData);
    }
    
    /**
     * 发送结束标志
     *
     * @throws IOException 发送异常
     */
    public void sendEndSignal() throws IOException {
        if (client == null || !client.isOpen()) {
            throw new IOException("WebSocket连接未建立或已关闭");
        }
        
        // 发送结束标志
        String endSignal = "{\"end\": true}";
        client.send(endSignal.getBytes());
    }
    
    /**
     * 关闭连接
     */
    public void close() {
        if (client != null && client.isOpen()) {
            client.close();
        }
    }
    
    /**
     * 同步方式进行语音识别
     *
     * @param audioData 完整的音频数据
     * @param params 转写参数
     * @return 转写结果
     * @throws Exception 转写过程中的异常
     */
    public String recognizeSpeech(byte[] audioData, ASRParams params) throws Exception {
        // 结果缓冲区
        StringBuilder resultBuilder = new StringBuilder();
        
        // 用于等待识别完成的信号
        CountDownLatch latch = new CountDownLatch(1);
        
        // 错误信息
        StringBuilder errorMessage = new StringBuilder();
        
        // 创建回调
        ASRCallback callback = new ASRCallback() {
            @Override
            public void onConnected(String sessionId) {
                // 连接成功后分段发送音频数据
                try {
                    // 分块发送音频数据（每40ms发送1280字节）
                    int frameSize = RealTimeASRConstant.DEFAULT_FRAME_SIZE;
                    for (int i = 0; i < audioData.length; i += frameSize) {
                        int length = Math.min(frameSize, audioData.length - i);
                        byte[] frame = new byte[length];
                        System.arraycopy(audioData, i, frame, 0, length);
                        sendAudioData(frame);
                        
                        // 控制发送速率，模拟实时发送
                        try {
                            Thread.sleep(40);
                        } catch (InterruptedException e) {
                            // 忽略中断异常
                        }
                    }
                    
                    // 发送结束标志
                    sendEndSignal();
                } catch (IOException e) {
                    errorMessage.append("发送音频数据失败: ").append(e.getMessage());
                    latch.countDown();
                }
            }
            
            @Override
            public void onResult(ASRResult result) {
                // 只处理最终结果
                if (result.isFinal() || result.isTranslation()) {
                    String text = result.getPlainText();
                    if (text != null && !text.isEmpty()) {
                        if (resultBuilder.length() > 0) {
                            resultBuilder.append("\n");
                        }
                        resultBuilder.append(text);
                    }
                }
            }
            
            @Override
            public void onError(String errorCode, String message) {
                errorMessage.append("错误 [").append(errorCode).append("]: ").append(message);
                latch.countDown();
            }
            
            @Override
            public void onClose() {
                latch.countDown();
            }
        };
        
        try {
            // 开始语音转写
            startRealTimeASR(params, callback);
            
            // 等待转写完成
            latch.await(60, TimeUnit.SECONDS);
            
            // 检查是否有错误
            if (errorMessage.length() > 0) {
                throw new Exception(errorMessage.toString());
            }
            
            return resultBuilder.toString();
        } finally {
            // 关闭连接
            close();
        }
    }
    
    /**
     * 从输入流读取PCM音频数据
     *
     * @param inputStream 音频输入流
     * @return 音频数据字节数组
     * @throws IOException 读取过程中的异常
     */
    public byte[] readAudioFromStream(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        
        return outputStream.toByteArray();
    }
}